package swing;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;

import container.WeaponTraitDescription;
import enums.FieldNames;

/**
 * Frame to crate and edit {@link WeaponTraitDescription}s.
 * 
 * @author Marcus
 * 
 */
public class WeaponTraitCreationFrame extends JFrame implements ActionListener {

	/** Generated serial ID */
	private static final long serialVersionUID = 8883168955824265348L;
	private WeaponTraitDescription changedWeaponTraitDiscription;
	private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
	private boolean changed;

	private JTextField traitNameField;
	private JTextField traitCodeField;
	private JTextField traitFormulaField;
	private JTextArea descriptionTextArea;

	public static final String OK = "OK";
	public static final String CANCEL = "Cancel";

	public static void main(String args[]) {
		WeaponTraitCreationFrame frame = new WeaponTraitCreationFrame();
		frame.start(null);
	}
	
	public WeaponTraitCreationFrame(){
		designFrame();
	}

	/**
	 * Adds an {@link ActionListener} to this frame.
	 * 
	 * @param listener
	 *            listener to add
	 */
	public void addActionListener(ActionListener listener) {
		this.actionListeners.add(listener);
	}

	/**
	 * Removes an {@link ActionListener} from this frame.
	 * 
	 * @param listener
	 *            listener to remove
	 */
	public void removeActionListener(ActionListener listener) {
		this.actionListeners.remove(listener);
	}

	/**
	 * Returns the trait.
	 * 
	 * @return the trait
	 */
	public WeaponTraitDescription getTrait() {
		if (this.changed) {
			this.changedWeaponTraitDiscription
					.setDescription(this.descriptionTextArea.getText());
			this.changedWeaponTraitDiscription.setTraitCode(this.traitCodeField
					.getText());
			this.changedWeaponTraitDiscription.setTraitName(this.traitNameField
					.getText());
			this.changedWeaponTraitDiscription
					.setRatingFormula(this.traitFormulaField.getText());
			boolean isRated = this.traitFormulaField.getText().contains("X")
					|| this.traitFormulaField.getText().contains("x");
			this.changedWeaponTraitDiscription.setRatedTrait(isRated);
		}

		return this.changedWeaponTraitDiscription;
	}

	/**
	 * Opens the frame which allows to edit/create a new weapon trait.
	 * 
	 * <p>
	 * If the passed {@link WeaponTraitDescription} is {@code null} then a new
	 * {@link WeaponTraitDescription} is created.
	 * </p>
	 * 
	 * @param trait
	 *            trait which is edited.
	 */
	public void start(WeaponTraitDescription trait) {
		init(trait);
		updateTextComponents();
		setVisible(true);
		repaint();
	}
	/**
	 * Designes the Frame with all its components.
	 */
	private void designFrame() {
		JComponent textComponent = createTextFieldComponent();
		textComponent.repaint();
		JComponent descriptionComponent = createDescriptionArea();
		descriptionComponent.repaint();
		JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
				textComponent, descriptionComponent);

		splitPane.setVisible(true);
		splitPane.setOneTouchExpandable(true);
		splitPane.setDividerLocation(150);

		// Provide minimum sizes for the two components in the split pane
		Dimension minimumSize = new Dimension(500, 200);
		textComponent.setMinimumSize(minimumSize);
		descriptionComponent.setMinimumSize(minimumSize);

		add(splitPane, BorderLayout.CENTER);
		add(createButtonPanel(), BorderLayout.PAGE_END);

		pack();
		setVisible(false);
	}

	/**
	 * @param trait
	 */
	private void init(WeaponTraitDescription trait) {
		this.changed = false;
		if (trait == null) {
			this.changedWeaponTraitDiscription = new WeaponTraitDescription();
			this.changedWeaponTraitDiscription
					.setDescription("Enter description of the trait here.");
			this.changedWeaponTraitDiscription
					.setRatingFormula("Enter the formula to calculate the cost here.");
			this.changedWeaponTraitDiscription
					.setTraitName("Enter the name of the trait here.");
			this.changedWeaponTraitDiscription
					.setTraitCode("Enter the code of the trait here.");
		} else {
			this.changedWeaponTraitDiscription = trait;
		}
	}

	private JPanel createButtonPanel() {
		JPanel buttonPanel = new JPanel(new GridLayout(1, 2));
		JButton okButton = new JButton(OK);
		JButton cancelButton = new JButton(CANCEL);

		okButton.addActionListener(this);
		cancelButton.addActionListener(this);

		buttonPanel.add(okButton);
		buttonPanel.add(cancelButton);

		return buttonPanel;
	}

	private JComponent createTextFieldComponent() {
		// Create the text fields
		this.traitNameField = new JTextField(20);
		this.traitCodeField = new JTextField(6);
		this.traitFormulaField = new JTextField(20);

		// Create the Labels for the text fields
		JLabel traitNameFieldLabel = new JLabel(FieldNames.TRAIT_NAME
				.getFieldName());
		traitNameFieldLabel.setLabelFor(this.traitNameField);
		JLabel traitCodeFieldLabel = new JLabel(FieldNames.TRAIT_CODE
				.getFieldName());
		traitCodeFieldLabel.setLabelFor(this.traitCodeField);
		JLabel traitFormulaFieldLabel = new JLabel(
				FieldNames.TRAIT_MULTIPLIER_FORMULA.getFieldName());
		traitFormulaFieldLabel.setLabelFor(this.traitFormulaField);

		// Lay out the text controls and the labels.
		JPanel textControlsPane = new JPanel();
		GridBagLayout gridbag = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();

		textControlsPane.setLayout(gridbag);

		JLabel[] labels = { traitNameFieldLabel, traitCodeFieldLabel,
				traitFormulaFieldLabel };
		JTextField[] textFields = { this.traitNameField, this.traitCodeField,
				this.traitFormulaField };
		addLabelTextRows(labels, textFields, gridbag, textControlsPane);

		c.gridwidth = GridBagConstraints.REMAINDER; // last
		c.anchor = GridBagConstraints.WEST;
		c.weightx = 1.0;
		textControlsPane.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createTitledBorder("Weapon Trait"), BorderFactory
						.createEmptyBorder(50, 50, 50, 50)));
		
		return textControlsPane;
	}

	/**
	 * 
	 */
	private void updateTextComponents() {
		this.traitNameField.setText(this.changedWeaponTraitDiscription
				.getTraitName());
		this.traitCodeField.setText(this.changedWeaponTraitDiscription
				.getTraitCode());
		this.traitFormulaField.setText(this.changedWeaponTraitDiscription
				.getRatingFormula());
		this.descriptionTextArea.setText(this.changedWeaponTraitDiscription.getDescription());
	}

	private JComponent createDescriptionArea() {
		this.descriptionTextArea = new JTextArea(
				);
		this.descriptionTextArea.setFont(new Font("Serif", Font.ITALIC, 16));
		this.descriptionTextArea.setLineWrap(true);
		this.descriptionTextArea.setWrapStyleWord(true);
		
		JScrollPane areaScrollPane = new JScrollPane(this.descriptionTextArea);
		areaScrollPane
				.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		areaScrollPane.setPreferredSize(new Dimension(250, 250));
		areaScrollPane.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createCompoundBorder(BorderFactory
						.createTitledBorder(FieldNames.TRAIT_DESCRIPTION
								.getFieldName()), BorderFactory
						.createEmptyBorder(5, 5, 5, 5)), areaScrollPane
						.getBorder()));

		return areaScrollPane;
	}

	private void addLabelTextRows(JLabel[] labels, JTextField[] textFields,
			GridBagLayout gridbag, Container container) {
		GridBagConstraints c = new GridBagConstraints();
		c.anchor = GridBagConstraints.EAST;
		int numLabels = labels.length;

		for (int i = 0; i < numLabels; i++) {
			c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
			c.fill = GridBagConstraints.NONE; // reset to default
			c.weightx = 0.0; // reset to default
			container.add(labels[i], c);

			c.gridwidth = GridBagConstraints.REMAINDER; // end row
			c.fill = GridBagConstraints.HORIZONTAL;
			c.weightx = 1.0;
			container.add(textFields[i], c);
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals(OK)) {
			this.changed = true;
		}

		if (e.getActionCommand().equals(CANCEL)) {
			this.changed = false;
		}


		for (ActionListener actionListener : this.actionListeners) {
			actionListener.actionPerformed(new ActionEvent(this, e.getID(), e
					.getActionCommand()));
		}
		
		dispose();
	}

}
